/*
 * @Author: czy
 * @Date: 2021-05-30 12:03:07
 * @LastEditTime: 2021-06-05 22:36:35
 */
#include "stdio.h"

#include "api/system.h"

static void showPartition(Partition *efp)
{
    printf("Partition(start=%p, head=%p)\n", efp, (Block *)(efp->head));
}

static void showBlock(Block *block)
{
    printf("Block(start=%p, end=%p, size=%d, previous=%p, next=%p)\n", block, (unsigned long)block + block->size - 1, block->size, block->previous, block->next);
}

static void partitionWalkByAddr(unsigned long handler)
{
    Partition *partition = (Partition *)handler;
    showPartition(partition);
    Block *block = (Block *)(partition->head);
    while (block != 0)
    {
        showBlock(block);
        block = (Block *)block->next;
    }
    printf("\n");
}

int testeFPartition(int argc, char *argv[])
{
	unsigned long handler = eFPartitionInit(0x200000, 64, 4);
	printf("Initialization.\n");
	partitionWalkByAddr(handler);

	unsigned long address[10];
	address[0] = eFPartitionAlloc(handler);
	printf("Allocate memory.\n");
	partitionWalkByAddr(handler);

	address[1] = eFPartitionAlloc(handler);
	address[2] = eFPartitionAlloc(handler);
	address[3] = eFPartitionAlloc(handler);
	printf("Continuously allocate memory.\n");
	partitionWalkByAddr(handler);

	address[4] = eFPartitionAlloc(handler);
	printf("Try to allocate too much memory.\n");
	partitionWalkByAddr(handler);

	eFPartitionFree(handler, address[1]);
	eFPartitionFree(handler, address[3]);
	eFPartitionFree(handler, address[0]);
	eFPartitionFree(handler, address[2]);
	printf("Disorderly release.\n");
	partitionWalkByAddr(handler);

	address[0] = eFPartitionAlloc(handler);
	address[1] = eFPartitionAlloc(handler);
	address[2] = eFPartitionAlloc(handler);
	printf("Request the released memory block again.\n");
	partitionWalkByAddr(handler);

	eFPartitionFree(handler, address[1]);
	eFPartitionFree(handler, address[0]);
	eFPartitionFree(handler, address[2]);
	for (int i = 0; i < 10; i++)
	{
		address[1] = eFPartitionAlloc(handler);
		eFPartitionFree(handler, address[1]);
		address[2] = eFPartitionAlloc(handler);
		address[0] = eFPartitionAlloc(handler);
		eFPartitionFree(handler, address[0]);
		eFPartitionFree(handler, address[2]);
	}
	printf("Repeated allocate and free.\n");
	partitionWalkByAddr(handler);
	return 1;
}

int testdPartition(int argc, char *argv[])
{
	unsigned long handler = dPartitionInit(0x200000, 1000);
	printf("Initialization.\n");
	partitionWalkByAddr(handler);

	unsigned long address[10];
	address[0] = dPartitionAlloc(handler, 120);
	printf("Allocate memory.\n");
	partitionWalkByAddr(handler);

	address[1] = dPartitionAlloc(handler, 230);
	address[2] = dPartitionAlloc(handler, 45);
	address[3] = dPartitionAlloc(handler, 10);
	printf("Continuously allocate memory.\n");
	partitionWalkByAddr(handler);

	address[4] = dPartitionAlloc(handler, 1200);
	printf("Try to allocate a block of memory that is too large.\n");
	partitionWalkByAddr(handler);

	dPartitionFree(handler, address[3]);
	dPartitionFree(handler, address[2]);
	dPartitionFree(handler, address[1]);
	printf("Release in reverse order.\n");
	partitionWalkByAddr(handler);

	address[1] = dPartitionAlloc(handler, 230);
	address[2] = dPartitionAlloc(handler, 45);
	address[3] = dPartitionAlloc(handler, 10);
	dPartitionFree(handler, address[1]);
	dPartitionFree(handler, address[2]);
	dPartitionFree(handler, address[3]);
	printf("Release in sequence.\n");
	partitionWalkByAddr(handler);

	address[1] = dPartitionAlloc(handler, 230);
	address[2] = dPartitionAlloc(handler, 45);
	address[3] = dPartitionAlloc(handler, 10);
	dPartitionFree(handler, address[1]);
	dPartitionFree(handler, address[3]);
	dPartitionFree(handler, address[2]);
	printf("Disorderly release.\n");
	partitionWalkByAddr(handler);

	dPartitionFree(handler, address[0]);
	printf("Free all memory blocks.\n");
	partitionWalkByAddr(handler);

	address[0] = dPartitionAlloc(handler, 100);
	address[1] = dPartitionAlloc(handler, 200);
	dPartitionFree(handler, address[0]);
	address[0] = dPartitionAlloc(handler, 400);
	printf("First-fit algorithm. (Allocate)\n");
	partitionWalkByAddr(handler);

	dPartitionFree(handler, address[0]);
	dPartitionFree(handler, address[1]);
	printf("First-fit algorithm. (Free)\n");
	partitionWalkByAddr(handler);
	return 1;
}